
import 'package:flutter/material.dart';
import 'package:wu_you/utils/arithmetic_utils.dart';
import 'package:wu_you/utils/density_utils.dart';
import 'package:toast/toast.dart';

enum AddPhotoType { add, select, delete }
enum AddPhotoModel { radioModel, checkModel }

typedef AddPhotoCallback = Future<bool> Function(
    int index, List<int> indexes, AddPhotoType type);
typedef DragCallback<T> = bool Function(
    List<T>indexes);
typedef SelectIndexedWidgetBuilder = Widget Function(
    BuildContext context, int index, bool select);
typedef GetHeightCallback = Function(double height);
class AddPhotoView extends StatefulWidget {
  const AddPhotoView(
      {Key key,
        @required this.itemBuilder,
        @required this.leftRightSpace,
        @required this.model,
        @required this.callback,
        this.crossAxisCount = 4,
        this.crossAxisSpacing = 10,
        this.mainAxisSpacing = 10,
        this.childAspectRatio = 1.0,
        this.defaultChild,
        this.dataSource,
        this.maxCount = 7,
        this.margin,
        this.isSelect = false,//是否选中
        this.hasSelect = false,
        this.deleteChild,
        this.cancelTap = false,
        this.onlyAddSelect,
        this.pointSelect = true,
        this.prompt,
        this.indexSelecte,
        this.color,
        this.showSort = false,
        this.dragCallback,this.itemHeight,this.hiddenAddBtn = true,this.isScroll = false,this.heightCallback})
      : super(key: key);
  final SelectIndexedWidgetBuilder itemBuilder;
  final int crossAxisCount;
  final double crossAxisSpacing;
  final double mainAxisSpacing;
  final double childAspectRatio;
  final double leftRightSpace;
  final Widget defaultChild;
  final List dataSource;
  final int maxCount;
  final EdgeInsets margin;
  final AddPhotoCallback callback;
  final AddPhotoModel model;
  final DragCallback dragCallback;
  final bool isSelect;
  final Widget deleteChild;
  final bool cancelTap;
  final bool onlyAddSelect;
  final bool pointSelect;//true为点击再取消,false 只会存在一个
  final String prompt;
  final bool hasSelect; //适配赵
  final List<int> indexSelecte;
  final Color color;
  final bool showSort;
  final double itemHeight;
  final bool hiddenAddBtn;
  final bool isScroll;
  final GetHeightCallback heightCallback;
  @override
  AddPhotoViewState createState() => AddPhotoViewState();
}

class AddPhotoViewState extends State<AddPhotoView> {
  List<Map<String, dynamic>> _items = [];
  int _row = 1;
  int _index = 0;
  double _itemHeight;

  @override
  void initState() {
    if (widget.dataSource == null) {
      // for (int i = 0; i < 8; i++) {
      //   _items.add("value");
      // }
      _addMap(0, widget.isSelect);
    } else {
      if (widget.defaultChild != null) {
        List<dynamic> data = ArithmeticUtils().removeNull(widget.dataSource);
        for (int i = 0; i < data.length; i++) {
          _addMap(i, widget.isSelect);
        }
        if (widget.onlyAddSelect != null) {
          _addMap(data.length, widget.onlyAddSelect);
        } else {
          _addMap(data.length, widget.isSelect);
        }
        ///有添加按钮
      } else {
        List<dynamic> data = ArithmeticUtils().removeNull(widget.dataSource);
        if (widget.indexSelecte != null) {
          for (int i = 0; i < data.length; i++) {
            if (widget.hasSelect) { //适配赵
              _addMap(i, widget.dataSource[i]['select']);
            } else {
              if (widget.indexSelecte.contains(i)) {
                _addMap(i, !widget.isSelect);
              } else {
                _addMap(i, widget.isSelect);
              }
            }
          }
          return;
        }
        for (int i = 0; i < data.length; i++) {
          if (widget.hasSelect) {//适配赵
            _addMap(i, widget.dataSource[i]['select']);
          } else {
            _addMap(i, widget.isSelect);
          }
        }
      }
    }
    super.initState();
  }

  @override
  Widget build(BuildContext context) {

    // _addMap(0, widget.isSelect);
    bool hiddenBtn = false;
    if(_items.length - 1  == widget.maxCount && widget.hiddenAddBtn){
      _items.removeLast();
      hiddenBtn = true;
    }
    int row = _items.length ~/ widget.crossAxisCount;
    if (_items.length % widget.crossAxisCount != 0) {
      row += 1;
    }
    _row = row;
    if (_row == 0) {
      _row = 1;
    }
    double levelSpace = widget.leftRightSpace;
    if (widget.margin != null) {
      levelSpace = widget.margin.left + widget.margin.right;
    }

    double itemHeight = (DensityUtil.screenW() -
        levelSpace -
        widget.crossAxisSpacing * (widget.crossAxisCount - 1)) /
        widget.crossAxisCount /
        widget.childAspectRatio;
    _itemHeight = itemHeight;
    double height = _row * itemHeight + (_row + 1) * widget.mainAxisSpacing;
    if(widget.itemHeight != null){
      height = widget.itemHeight;
    }
    if(widget.heightCallback != null){
      widget.heightCallback(height);
    }
    return Container(
        color: widget.color ?? Colors.transparent,
        height: height,
        child: GridView.builder(
          physics: widget.isScroll?AlwaysScrollableScrollPhysics (): NeverScrollableScrollPhysics(),
          padding: EdgeInsets.zero,
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: widget.crossAxisCount,
              crossAxisSpacing: widget.crossAxisSpacing,
              mainAxisSpacing: widget.mainAxisSpacing,
              childAspectRatio: widget.childAspectRatio),
          itemBuilder: (context, index) {
            Widget child;
            bool onlyOne = false;
            bool isSelect = _items[index]["isSelect"];
            if (widget.defaultChild != null && index == _items.length - 1) {
              if(!hiddenBtn){
                child = widget.defaultChild;
                onlyOne = true;
              }else{
                child = widget.itemBuilder(context, index, isSelect);
                if(widget.showSort){
                  child = addDragDrop(child, _items[index],index);
                  return child;
                }
              }
            } else if (widget.itemBuilder != null) {
              child = widget.itemBuilder(context, index, isSelect);
              if(widget.showSort){
                child = addDragDrop(child, _items[index],index);
                return child;
              }

            } else {
              child = Container(
                color: Colors.green,
              );
            }
            if (widget.deleteChild != null && onlyOne == false) {
              child = Stack(
                children: [
                  child,
                  Align(
                      alignment: Alignment.topRight,
                      child: GestureDetector(
                        child: widget.deleteChild,
                        onTap: ()async {
                          bool isDelete = await _handleCallback(index, AddPhotoType.delete);
                          if(isDelete){
                            _items.removeAt(index);
                            widget.dataSource.removeAt(index);
                            if(hiddenBtn){
                              _addMap(index, widget.hasSelect);
                            }
                            setState(() {});
                          }
                        },
                      )),
                ],
              );
            }
            return GestureDetector(
                behavior: HitTestBehavior.opaque,
                onTap: () async {
                  if (widget.callback != null) {
                    if (onlyOne == true) {

                      if (_items.length > widget.maxCount) {
                        Toast.show(widget.prompt ?? "超过最大数", context);
                        return;
                      }
                      if (await _handleCallback(index, AddPhotoType.add) ==
                          true) {
                        if(_items.length <= widget.maxCount){
                          print(_items.length);
                          _addMap(_items.length,
                              widget.onlyAddSelect ?? widget.isSelect,value:widget.dataSource[index]);
                          setState(() {});
                        }
                        // _addMap(_items.length,
                        //     widget.onlyAddSelect ?? widget.isSelect,value:widget.dataSource[index]);
                        // setState(() {});
                      };
                      return;
                    }
                    if (widget.cancelTap) {
                      return;
                    }
                    bool oldSel = _items[index]["isSelect"];
                    if (widget.model == AddPhotoModel.checkModel) {
                      //多选

                      _items[index]["isSelect"] = !_items[index]["isSelect"];
                    } else {
                      if (widget.pointSelect == true) {
                        bool temp = _items[index]["isSelect"];
                        _items.forEach((element) {
                          element["isSelect"] = false;
                        });
                        _items[index]["isSelect"] = !temp;
                      } else {
                        _items.forEach((element) {
                          element["isSelect"] = false;
                        });
                        _items[index]["isSelect"] = true;
                      }
                    }
                    _handleCallback(index, AddPhotoType.select).then((value){
                      if(value){
                        setState(() {});
                      }else{
                        _items[index]["isSelect"] = oldSel;
                      }
                    });

                  }
                },
                child: child);
          },
          itemCount: _items.length,
        ),
        margin: widget.margin);
  }

  void _addMap(int index, bool isSelect,{dynamic value}) {
    Map<String, dynamic> temp = {"index": index, "isSelect": isSelect};
    if(value != null){
      temp["value"] = value;
    }
    _items.add(temp);
  }

  void refresh(List data){
    _items = [];
    for (int i = 0; i < data.length; i++) {
      if (widget.hasSelect) {//适配赵
        _addMap(i, widget.dataSource[i]['select']);
      } else {
        _addMap(i, widget.isSelect);
      }
    }
      setState(() {

      });
  }

  Future<bool> _handleCallback(int index, AddPhotoType type,
      {bool isAdd}) async {
    List<int> indexes = [];
    if (widget.model == AddPhotoModel.checkModel) {
      ///多选回调
      _items.forEach((e) {
        int a = e["index"];
        if (e["isSelect"] == true) {
          indexes.add(a);
        }
      });
    } else {
      if (widget.pointSelect == true) {
        _items.forEach((e) {
          int a = e["index"];
          if (e["isSelect"] == true) {
            indexes.add(a);
          }
        });
      } else {
        indexes = [index];
      }
    }
    return widget.callback(index, indexes, type);
  }
  dynamic _movingValue;
  Widget addDragDrop(Widget child,dynamic value,int index) {
    return LongPressDraggable(
      child: DragTarget(
        onAccept: (moveData){
          print('=== onAccept: $moveData ==> $value');
          exchangeItem(moveData, value, true,index);
        },
        onLeave: (moveData) {
          // print('=== onLeave: $moveData ==> $value');
        },
        onWillAccept: (moveData) {
          print('=== onWillAccept: $moveData ==> $value');
          var accept = moveData != null;
          if (accept) {
            exchangeItem(moveData, value, false,index);
          }
          return accept;
        },
        builder: (context,data,rejects){
          return baseItem(value,Colors.blue,child);
        },
      ),
      data: value,
      feedback: baseItem(value,Colors.green.withOpacity(0.8),child),
      onDragStarted: () {
        //开始拖动，备份数据源
        // print('=== onDragStarted');
        setState(() {
          _movingValue = value;
        });
      },
      onDraggableCanceled: (Velocity velocity, Offset offset) {
        // print('=== onDraggableCanceled');
        setState(() {
          _movingValue = null;//清空标记进行重绘
        });
      },
      onDragCompleted: () {
        // print('=== onDragCompleted');
      },
    );
  }
  // 重新排序
  void exchangeItem(moveData, toData, onAccept,int index) {
    setState((){
      var toIndex = _items.indexOf(toData);
      _items.remove(moveData);
      _items.insert(toIndex, moveData);

      if(widget.dataSource != null){

        if(onAccept && widget.dragCallback != null) {
          var temp = [];
          temp.addAll(_items);
          temp.removeWhere((element) => element["index"] == 0);
          var real = temp.map((e) => e["value"]).toList();
          widget.dragCallback(real);
        }
      }
      if (onAccept) {
        _movingValue = null;
      }
    });
  }
  Widget baseItem(value, bgColor,Widget child) {
    if (value == _movingValue) {
      return Container();
    }
    return Container(
      width: 110,
      height: 110,
      color: bgColor,
      child: child,
    );
  }
}
